package sidecar

import (
	sidecarUtils "lqq/sidecar/utils"
	"time"

	CMap "github.com/orcaman/concurrent-map"
)

type client struct {
	CLIENTID     string
	sendMsgChan  chan *requestMsg
	serviceStore CMap.ConcurrentMap
	rs           *nacosRegisterServer
}

func newClient(id string, nacosAddrs []string) *client {
	c := &client{
		CLIENTID:     id,
		serviceStore: CMap.New(),
		rs:           newNacosRegisterServer(nacosAddrs),
	}
	go c.monitorRegister()
	go c.monitorSend()
	return c
}

func (c *client) getService(serviceName string) (*service, bool) {
	s, ok := c.serviceStore.Get(serviceName)
	if !ok {

		return nil, false
	}
	return s.(*service), true
}

func (c *client) monitorSend() {
	for {
		select {
		case msg := <-c.sendMsgChan:
			s, ok := c.getService(msg.reqHeader.ServiceName)
			if ok {
				if s.canUse {
					s.putRequestMsg(msg)
				} else {
					if s.lastRefreshTime.Sub(time.Now()) > 3*time.Second {
						//请求的服务没有一个实例，但3秒以上没有请求过，再请求一次nacos获取新的实例
						requestRegisterServerInstToGetAddrs(s, c, msg)
					} else {
						
						//请求的服务没有一个实例而且先前已经请求过，返回报错
						h := &RequestHeader{
							StatusCode: NETWORK_ERR,
							TRACEID:    msg.reqHeader.TRACEID,
							REQID:      msg.reqHeader.REQID,
						}
						msg.respHeader = h
						msg.semaphore <- true

					}
				}

			} else {
				//没有获取到任何该服务的信息，为第一次请求该服务，先请求一次nacos
				s = newService()
				requestRegisterServerInstToGetAddrs(s, c, msg)
			}
		case <-time.After(10 * time.Second):
			logger.info("10 秒还没收到任何消息！")
		}
	}
}

func requestRegisterServerInstToGetAddrs(s *service, c *client, msg *requestMsg) {
	rsOne, ok := c.rs.getOneInstance()
	if ok {
		rd := &getAddrsReqData{
			serviceName: msg.reqHeader.ServiceName,
			segin:       make(chan bool),
			ok:          false,
			result:      make([]string, 0),
		}
		rsOne.reqeustGetAddrs(rd)
		select {
		case <-rd.segin:
			if rd.ok {
				flag := false
				for i := 0; i < len(rd.result); i++ {
					si, err := newServiceInst(s, sidecarUtils.UUID(), rd.result[i])
					if err != nil {
						logger.error(err.Error())
						continue
					}
					s.addInst(si)
					flag = true
				}
				if flag {
					s.canUse = true
					s.putRequestMsg(msg)
				}

			}

		case <-time.After(4 * time.Second):
			//该nacos太慢，4秒还没返回，返回出错且将该nacos实例标志为不可用
			h := &RequestHeader{
				StatusCode: NETWORK_ERR,
				TRACEID:    msg.reqHeader.TRACEID,
				REQID:      msg.reqHeader.REQID,
			}
			msg.respHeader = h
			msg.semaphore <- true
			c.rs.putErrInstances(rsOne)
		}
		
	} else {
		//nacos全部失效，直接返回出错
		h := &RequestHeader{
			StatusCode: NETWORK_ERR,
			TRACEID:    msg.reqHeader.TRACEID,
			REQID:      msg.reqHeader.REQID,
		}
		msg.respHeader = h
		msg.semaphore <- true
	}
	c.serviceStore.Set(msg.reqHeader.ServiceName, s)
	s.lastRefreshTime = time.Now()
}

func (c *client) monitorRegister() {
	for {
		<-time.After(17 * time.Second)
		for _, serviceName := range c.serviceStore.Keys() {
			ser, ok := c.getService(serviceName)
			if ok {
				addrs, err := c.rs.getAddrs(serviceName)
				if err != nil {
					logger.error(err.Error())
					continue
				}
				if len(addrs) == 0 {
					c.serviceStore.Remove(serviceName)
					ser.destroy()
					continue
				}
				ser.refreshInstance(addrs)
			}
		}
	}
}
